home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 1.iso / dist / fw_freetype2.idb / usr / freeware / doc / freetype2 / cache.txt.z / cache.txt
Text File  |  2001-10-09  |  10KB  |  268 lines

  1.                The FreeType 2 cache sub-system explained
  2.                         (c) 2000 David Turner
  3.  
  4.             -----------------------------------------------
  5.  
  6. Introduction :
  7. --------------
  8.  
  9.   this document describes the caching sub-system that comes
  10.   with the FreeType library, version 2.0. Note that unlike
  11.   the rest of the library, this code is still in beta stage
  12.   and might still suffer slight changes in the future.
  13.  
  14.   Its basic design shouldn't evolve though and is explained
  15.   in this paper.
  16.  
  17.  
  18. I. Requirements and Design Goals:
  19. ---------------------------------
  20.  
  21.   The FT2 cache sub-system was designed to implement caching
  22.   of glyph images. However, it is extremely flexible and can
  23.   be easily extended to cache other kind of data like metrics,
  24.   character maps, coverage tables, etc..
  25.  
  26.  
  27. II. Base Concepts:
  28. ------------------
  29.  
  30.  1. The cache manager object:
  31.  
  32.    at the heart of the caching sub-system is a single object
  33.    called the "cache manager". It is used to deal with FT_Face
  34.    and FT_Size objects, as well as to manager a LRU list of
  35.    abstract "cache nodes".
  36.  
  37.    a. caching FT_Face and FT_Size objects:
  38.  
  39.      each FT_Face object created by FreeType 2 can take from
  40.      a few hundred bytes to several tens of kilobytes, depending
  41.      on the original font's file format as well as its content.
  42.  
  43.      there is no easy way to compute the size of a given FT_Face
  44.      object, so it's always a good idea to assume that it is
  45.      large and to want to limit the number of live face objects
  46.      as much as possible.
  47.  
  48.      similarly, each FT_Face can have one or more FT_Size childs,
  49.      whose byte size depends heavily on the font format.
  50.  
  51.      the first purpose of the cache manager is to provide a
  52.      small cache for FT_Face and FT_Size objects. Basically,
  53.      an application can use it as follows:
  54.  
  55.        - each font face is described to the cache manager
  56.          through a typeless pointer, called a FTC_FaceID.
  57.  
  58.          the cache manager itself doesn't interpret or use
  59.          the value of FTC_FaceIDs directly. Rather, it passes
  60.          them to a user-provided function called a
  61.          "face requester". see the defintion of the
  62.          FTC_Face_Requester type in <freetype/ftcache.h>
  63.          for details..
  64.  
  65.          the face requester is in charge of translating a given
  66.          face into into a real new FT_Face object that is
  67.          returned to the cache manager. The latter will keep
  68.          the face object alive as long as it needs to.
  69.  
  70.          the face requester is unique and must be passed
  71.          to the function named FTC_Manager_New used to
  72.          create/initialise a new cache manager.
  73.  
  74.  
  75.        - to lookup a given FT_Face, call the function
  76.          FTC_Manager_Lookup_Face as in the following code:
  77.  
  78.               FTC_Manager_Lookup_Face( manager,
  79.                                        face_id,
  80.                                        &face );
  81.  
  82.          if the corresponding FT_Face object is kept in
  83.          the cache manager's list, it will be returned
  84.          directly. Otherwise, this function will call
  85.          the user-provided face requester to create
  86.          a new FT_Face object, add it to the manager's
  87.          list to finally return it.
  88.  
  89.          FT_Face objects are always destroyed by the cache
  90.          manager. An application that uses the cache
  91.          sub-system should never call FT_Done_Face !!
  92.  
  93.        - to lookup a given FT_Size and FT_Face, call the
  94.          function FTC_Manager_Lookup_Size, as in:
  95.  
  96.               FTC_Manager_Lookup_Size( manager,
  97.                                        ftc_font,
  98.                                        &face,
  99.                                        &size );
  100.  
  101.          where "ftc_font" is a pointer to a FTC_Font descriptor
  102.          (a structure containing a FTC_FaceIDs and character
  103.           dimensions corresponding to the desired FT_Size).
  104.  
  105.          note that the function returns both a FT_Face and
  106.          a FT_Size object. You don't need to call
  107.          FTC_Manager_Lookup_Face before it !!
  108.  
  109.          also note that returned FT_Size objects are always
  110.          destroyed by the cache manager. A client application
  111.          that uses it should never call FT_Done_Size !!
  112.  
  113.  
  114.      the big advantage of using FTC_FaceIDs is that is
  115.      makes the caching sub-system completely independent
  116.      of the way font files are installed / listed / managed
  117.      in your application. In most implementations, a FTC_FaceID
  118.      is really a pointer to an application-specific structure
  119.      that describe the source font file + face index.
  120.  
  121.  
  122.     b - manage a MRU list of abstract "cache nodes":
  123.  
  124.      the second role of the cache manager is to hold and manager
  125.      a list of abstract "cache nodes". The list is always sorted
  126.      in most-recently-used order. The manager always ensure that
  127.      the total size of nodes in memory doesn't over-reach a
  128.      certain threshold, by eliminating "old" nodes when
  129.      necessary.
  130.  
  131.      the cache manager doesn't know much about the cache nodes:
  132.  
  133.        - it knows how to move them in its list
  134.        - it knows how to destroy them when they're too old
  135.        - it knows how to "size" them (i.e. compute their byte
  136.          size in memory)
  137.  
  138.  
  139.  2. Cache objects:
  140.  
  141.    the cache manager doesn't create new cache nodes however, this
  142.    is the charge of what are called "cache objects".
  143.  
  144.    Basically, each cache object is in charge of managing cache
  145.    nodes of a certain type. Its role is to:
  146.  
  147.      - provide a simple description of its cache nodes to the
  148.        manager (i.e. through a FTC_CacheNode_Class structure)
  149.  
  150.      - provide a high-level API that can be called by client
  151.        applications to lookup cache nodes of the corresponding
  152.        type.
  153.  
  154.        this function usually creates new nodes when they're not
  155.        available yet.
  156.  
  157.      - also, and even though this is completely transparent to
  158.        the applications and the cache manager, each cache object
  159.        manages "node sets", where each set contains cache nodes
  160.        usually correspond to the same font face + font size.
  161.  
  162.  
  163.    For example, the cache sub-system currently comes with two
  164.    distinct cache classes:
  165.  
  166.      - a FTC_Image_Cache, which is used to cache FT_Glyph images
  167.        (with one FT_Glyph per cache node).
  168.  
  169.  
  170.      - a FTC_SBit_Cache, which is used to cache small glyph bitmaps
  171.        ("sbit" means "embedded bitmaps" in digital typography).
  172.  
  173.  
  174.    the small bitmaps glyph is useful because storing one glyph
  175.    image per cache node isn't memory efficient when the data
  176.    associated to each node is very small. Indeed, each cache
  177.    node has a minimal size of 20 bytes, which is huge when
  178.    your data is an 8x8 monochrome bitmap :-)
  179.  
  180.    Hence, a FTC_SBit_Cache is capable of storing several
  181.    contiguous sbits in a single cache node, resulting in much
  182.    higher cached glyphs / total cache size.
  183.  
  184.    an application can lookup a FT_Glyph image with a FTC_Image_Cache
  185.    by calling:
  186.  
  187.         error = FTC_Image_Cache_Lookup( image_cache,
  188.                                         ftc_font,
  189.                                         glyph_index,
  190.                                         &ft_glyph );
  191.  
  192.    or a FTC_SBit (small bitmap descriptor) by calling:
  193.  
  194.        error = FTC_SBit_Cache_Lookup( sbit_cache,
  195.                                       ftc_font,
  196.                                       glyph_index,
  197.                                       &ftc_sbit );
  198.  
  199. III. Extending the cache sub-system:
  200.  
  201.  It is possible to extend the current cache sub-system by
  202.  providing your own cache class and register it in the cache
  203.  manager. That might be useful to cache other kind of data
  204.  in the sub-system, like glyph metrics (without images),
  205.    
  206.  To do it, you'll need to read the cache sub-system public
  207.  header files rather heavily :-) Fortunately, they're pretty
  208.  well commented and should guide you to your goal.
  209.  
  210.  Note that the cache sub-system already provides two "abstract
  211.  cache" classes that can be re-used by your own implementation:
  212.  
  213.  
  214.  1. The abstract "FTC_GlyphCache" class:
  215.  
  216.    this code is used to implement an abstract "glyph cache",
  217.    i.e. one that simply maps one glyph data per cache node.
  218.  
  219.    it is sub-classed by FTC_Image_Cache, whose implementation
  220.    only consists in simple code to store a FT_Glyph in each
  221.    cache node.
  222.  
  223.    you could sub-class it in your application to store glyph
  224.    images in a different format, for example.
  225.  
  226.    see the files <freetype/cache/ftcglyph.h> and
  227.    "src/cache/ftcglyph.h" for details.
  228.  
  229.  
  230.  2. The abstract "FTC_ChunkCache" class:
  231.  
  232.    this code is used to implement an abstract "glyph chunk cache".
  233.    it's very similar to a FTC_GlyphCache, except that it is capable
  234.    of storing several glyph-specific elements per cache node.
  235.  
  236.    it is sub-classed by FTC_SBit_Cache, whose implementation
  237.    only consists in code to store a FTC_SBitRec record in each
  238.    node element.
  239.  
  240.    you could sub-class it in your application to store small
  241.    glyph data, like metrics, glyph names, wathever.
  242.  
  243.    see the files <freetype/cache/ftcchunk.h> and
  244.    "src/cache/ftcchunk.h" for details..
  245.  
  246.  
  247.   Note that the two abstract caches are rather complex because
  248.   they use "glyph sets". Each glyph set corresponds to a single
  249.   font face + font size combination. both caches are also
  250.   glyph-specific, though it is perfectly possible to use
  251.   broader selection criterion, here are a few examples:
  252.  
  253.     - caching language coverage maps corresponding to
  254.       a given font face + language combination
  255.  
  256.     - caching charmaps, layout tables, and other global
  257.       data..
  258.  
  259.     - caching (font_face + font_size) specific "latin1"
  260.       ascender + descender
  261.  
  262.  
  263.   as you can see, a lot is possible with this design :-)
  264.  
  265.  
  266.  
  267.  
  268.